﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Passwords.Services;
using System.Collections.ObjectModel;
using Passwords.Models;
using System.Windows.Input;
using System.Windows;
using System.Collections;
using System.Windows.Controls;
using System.Windows.Interactivity;
using Microsoft.Win32;
using System.Runtime.Serialization;
using System.IO;
using System.Diagnostics;
using Passwords.DAL;

namespace Passwords.ViewModels
{
    public class BackupViewModel : ViewModelBase, IDisposable
    {

        public BackupViewModel(AppViewModel appViewModel)
            : base()
        {
            this.appViewModel = appViewModel;
            SyncContext = SyncContext.Current;
            BindCommands();
        }

        public void Dispose()
        {
            UnbindCommands();
        }

        protected AppViewModel appViewModel;

        private IList selectedBackups;

        public IList SelectedBackups
        {
            get { return selectedBackups; }
            set
            {
                if (selectedBackups != value)
                {
                    selectedBackups = value;
                    OnPropertyChanged("SelectedBackups");
                    Backup selected = value != null && value.Count > 0 ? value[0] as Backup : null;
                    SelectedBackup = selected;
                }
            }
        }

        private Backup selectedBackup;

        public Backup SelectedBackup
        {
            get { return selectedBackup; }
            set
            {
                if (selectedBackup != value)
                {
                    selectedBackup = value;
                    OnPropertyChanged("SelectedBackup");
                }
            }
        }


        public ObservableCollection<Backup> Backups { get { return SyncContext.Backups; } }

        public ObservableCollection<NamedDevice> Devices { get { return SyncContext.NamedDevices; } }

        public SyncContext SyncContext { get; private set; }


        private void BindCommands()
        {
            BindCommand(BackupCommands.Delete, DeleteCommand, CanDeleteCommand);
            BindCommand(BackupCommands.Restore, RestoreCommand, IsSingleSelectedCommand);
            BindCommand(BackupCommands.Export, ExportCommand, IsSingleSelectedCommand);
            BindCommand(BackupCommands.Open, OpenCommand, IsSingleSelectedCommand);
            BindCommand(BackupCommands.Import, ImportCommand);
        }

        private void OpenCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;

            Backup backup = SelectedBackup;
            if (backup != null)
            {
                appViewModel.Backup = backup;
                appViewModel.AppDisplayMode = AppDisplayMode.Login;
            }
        }


        private void BackupCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
        }

        private void DeleteCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
            if (selectedBackups == null) return;
            if (MessageBox.Show("Delete all selected backups?", "DELETE", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {
                foreach (Backup backup in selectedBackups.Cast<Backup>().ToArray())
                {
                    SyncContext.DeleteBackup(backup);
                }
            }
        }

        private void CanDeleteCommand(object sender, CanExecuteRoutedEventArgs e)
        {
            e.Handled = true;
            e.CanExecute = selectedBackup != null;

        }

        private void IsSingleSelectedCommand(object sender, CanExecuteRoutedEventArgs e)
        {
            e.Handled = true;
            e.CanExecute = selectedBackups != null && selectedBackups.Count == 1;

        }

        private void ExportCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
            if (SelectedBackup != null)
            {
                Export(SelectedBackup);
            }
        }

        private void Export(Backup backup)
        {
            if (backup != null)
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.Title = "Export Backup";
                dlg.DefaultExt = ".xml";
                dlg.Filter = "xml|*.xml|Text|*.txt|All Files|*.*";
                bool? result = dlg.ShowDialog();
                if (result.HasValue && result.Value)
                {
                    string fileName = dlg.FileName;
                    DataContractSerializer serializer = new DataContractSerializer(typeof(Backup));
                    using (FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
                    {
                        serializer.WriteObject(stream, backup);
                    }
                }
            }
        }

        private void ImportCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Title = "Import Backup";
            dlg.DefaultExt = ".xml";
            dlg.Filter = "xml|*.xml|Text|*.txt|All Files|*.*";
            bool? result = dlg.ShowDialog();
            if (result.HasValue && result.Value)
            {
                string fileName = dlg.FileName;
                DataContractSerializer serializer = new DataContractSerializer(typeof(Backup));
                using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    try
                    {
                        Backup backup = serializer.ReadObject(stream) as Backup;
                        backup.Id = Guid.NewGuid();
                        if (!backup.Name.StartsWith("Import "))
                        {
                            backup.Info = backup.Name + " from " + backup.DateCreated.ToShortDateString() + ", " + backup.PasswordCount.ToString() + " passwords.";
                            backup.Name = "Import of " + backup.Name;
                        }
                        backup.IsImported = true;
                        backup.DateCreated = DateTime.Now;
                        SyncContext.SaveBackup(backup);
                        Backups.Insert(0, backup);
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
            }

        }

        private void RestoreCommand(object sender, ExecutedRoutedEventArgs e)
        {
            e.Handled = true;
            if (MessageBox.Show("Restore your passwords with the selected backup and loose all changes made on your current paswords?", "RESTORE", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
            {

                Backup backup = SelectedBackup;
                if (backup != null)
                {
                    backup.Restore = true;
                    appViewModel.Backup = backup;
                    appViewModel.AppDisplayMode = AppDisplayMode.Login;
                }
            }

        }

    }
}
